import unittest
from typing import List

from jce import JceField, JceStruct, types


class SsoServerInfo(JceStruct):
    server: types.STRING = JceField(jce_id=1)
    port: types.INT = JceField(jce_id=2)
    location: types.STRING = JceField(jce_id=8)
    extra: str
    extra_default: str = "extra"


class ServerListResponse(JceStruct):
    server_list: types.LIST[SsoServerInfo] = JceField(jce_id=2)


class TestStruct(unittest.TestCase):
    def test_struct_encode(self):
        byte = SsoServerInfo(
            server="rcnb", port=8000, location="rcnb", extra="xxx"
        ).encode()
        self.assertEqual(
            byte, bytes.fromhex("16 04 72 63 6e 62 21 1f 40 86 04 72 63 6e 62")
        )

    def test_struct_decode(self):
        a = SsoServerInfo.decode(
            bytes.fromhex("16 04 72 63 6e 62 21 1f 40 86 04 72 63 6e 62"),
            extra="xxx",
        )
        b = SsoServerInfo(
            server="rcnb", port=8000, location="rcnb", extra="xxx"
        )
        self.assertEqual(a, b)

    def test_struct_nested_encode(self):
        raw = ServerListResponse.parse_obj(
            {
                "server_list": [
                    {
                        "server": "193.112.231.60",
                        "port": 8080,
                        "location": "sz",
                        "extra": "xxx",
                    },
                    {
                        "server": "42.81.172.215",
                        "port": 8080,
                        "location": "tj",
                        "extra": "xxx",
                    },
                    {
                        "server": "14.22.3.114",
                        "port": 8080,
                        "location": "sz",
                        "extra": "xxx",
                    },
                    {
                        "server": "14.215.138.110",
                        "port": 443,
                        "location": "sz",
                        "extra": "xxx",
                    },
                    {
                        "server": "42.81.169.100",
                        "port": 80,
                        "location": "tj",
                        "extra": "xxx",
                    },
                    {
                        "server": "114.221.144.76",
                        "port": 14000,
                        "location": "sh",
                        "extra": "xxx",
                    },
                    {
                        "server": "113.96.12.224",
                        "port": 443,
                        "location": "sz",
                        "extra": "xxx",
                    },
                    {
                        "server": "42.81.170.122",
                        "port": 8080,
                        "location": "tj",
                        "extra": "xxx",
                    },
                    {
                        "server": "114.221.148.67",
                        "port": 80,
                        "location": "sh",
                        "extra": "xxx",
                    },
                    {
                        "server": "msfwifi.3g.qq.com",
                        "port": 8080,
                        "location": "others",
                        "extra": "xxx",
                    },
                    {
                        "server": "42.81.172.63",
                        "port": 80,
                        "location": "tj",
                        "extra": "xxx",
                    },
                ]
            }
        )
        encoded = bytes.fromhex(
            "29000B0A160E3139332E3131322E3233312E3630211F908602737A0B"
            "0A160D34322E38312E3137322E323135211F908602746A0B0A160B31"
            "342E32322E332E313134211F908602737A0B0A160E31342E3231352E"
            "3133382E3131302101BB8602737A0B0A160D34322E38312E3136392E"
            "31303020508602746A0B0A160E3131342E3232312E3134342E373621"
            "36B0860273680B0A160D3131332E39362E31322E3232342101BB8602"
            "737A0B0A160D34322E38312E3137302E313232211F908602746A0B0A"
            "160E3131342E3232312E3134382E36372050860273680B0A16116D73"
            "66776966692E33672E71712E636F6D211F9086066F74686572730B0A"
            "160C34322E38312E3137322E363320508602746A0B"
        )
        self.assertEqual(raw.encode(), encoded)

    def test_struct_nested_decode(self):
        raw = ServerListResponse.parse_obj(
            {
                "server_list": [
                    {
                        "server": "193.112.231.60",
                        "port": 8080,
                        "location": "sz",
                        "extra": "xxx",
                    },
                    {
                        "server": "42.81.172.215",
                        "port": 8080,
                        "location": "tj",
                        "extra": "xxx",
                    },
                    {
                        "server": "14.22.3.114",
                        "port": 8080,
                        "location": "sz",
                        "extra": "xxx",
                    },
                    {
                        "server": "14.215.138.110",
                        "port": 443,
                        "location": "sz",
                        "extra": "xxx",
                    },
                    {
                        "server": "42.81.169.100",
                        "port": 80,
                        "location": "tj",
                        "extra": "xxx",
                    },
                    {
                        "server": "114.221.144.76",
                        "port": 14000,
                        "location": "sh",
                        "extra": "xxx",
                    },
                    {
                        "server": "113.96.12.224",
                        "port": 443,
                        "location": "sz",
                        "extra": "xxx",
                    },
                    {
                        "server": "42.81.170.122",
                        "port": 8080,
                        "location": "tj",
                        "extra": "xxx",
                    },
                    {
                        "server": "114.221.148.67",
                        "port": 80,
                        "location": "sh",
                        "extra": "xxx",
                    },
                    {
                        "server": "msfwifi.3g.qq.com",
                        "port": 8080,
                        "location": "others",
                        "extra": "xxx",
                    },
                    {
                        "server": "42.81.172.63",
                        "port": 80,
                        "location": "tj",
                        "extra": "xxx",
                    },
                ]
            }
        )
        encoded = bytes.fromhex(
            "100129000B0A160E3139332E3131322E3233312E3630211F9030014C"
            "5C600870018602737A96066F74686572730B0A160D34322E38312E31"
            "37322E323135211F9030014C5C600870018602746A960374656C0B0A"
            "160B31342E32322E332E313134211F9030014C5C600870018602737A"
            "960374656C0B0A160E31342E3231352E3133382E3131302101BB3001"
            "4C5C600870018602737A960374656C0B0A160D34322E38312E313639"
            "2E313030205030014C5C600870018602746A960374656C0B0A160E31"
            "31342E3232312E3134342E37362136B030014C5C6008700186027368"
            "960374656C0B0A160D3131332E39362E31322E3232342101BB30014C"
            "5C600870018602737A960374656C0B0A160D34322E38312E3137302E"
            "313232211F9030014C5C600870018602746A960374656C0B0A160E31"
            "31342E3232312E3134382E3637205030014C5C600870018602736896"
            "0374656C0B0A16116D7366776966692E33672E71712E636F6D211F90"
            "30014C5C60087C86066F746865727396066F74686572730B0A160C34"
            "322E38312E3137322E3633205030014C5C600870018602746A960374"
            "656C0B39000B0A160E3139332E3131322E3233312E3630211F903001"
            "4C5C600870018602737A96066F74686572730B0A160D34322E38312E"
            "3137322E323135211F9030014C5C600870018602746A960374656C0B"
            "0A160B31342E32322E332E313134211F9030014C5C60087001860273"
            "7A960374656C0B0A160E31342E3231352E3133382E3131302101BB30"
            "014C5C600870018602737A960374656C0B0A160D34322E38312E3136"
            "392E313030205030014C5C600870018602746A960374656C0B0A160E"
            "3131342E3232312E3134342E37362136B030014C5C60087001860273"
            "68960374656C0B0A160D3131332E39362E31322E3232342101BB3001"
            "4C5C600870018602737A960374656C0B0A160D34322E38312E313730"
            "2E313232211F9030014C5C600870018602746A960374656C0B0A160E"
            "3131342E3232312E3134382E3637205030014C5C6008700186027368"
            "960374656C0B0A16116D7366776966692E33672E71712E636F6D211F"
            "9030014C5C60087C86066F746865727396066F74686572730B0A160C"
            "34322E38312E3137322E3633205030014C5C600870018602746A9603"
            "74656C0B425FE636545138406C7C80029005ACBCC900050A160E3130"
            "392E3234342E3132392E3135205030014C500360087C8602737A9606"
            "6F74686572730B0A160D34322E38312E3136392E313035205030014C"
            "500360087C8602746A960374656C0B0A160C3131332E39362E31332E"
            "3434205030014C500360087C8602737A960374656C0B0A160E313134"
            "2E3232312E3134342E3232205030014C500360087C86027368960374"
            "656C0B0A160D34322E38312E3136392E313035205030014C50036008"
            "7C8602746A960374656C0BD900050A160E3130392E3234342E313239"
            "2E3135205030014C500360087C8602737A96066F74686572730B0A16"
            "0D34322E38312E3136392E313035205030014C500360087C8602746A"
            "960374656C0B0A160C3131332E39362E31332E3434205030014C5003"
            "60087C8602737A960374656C0B0A160E3131342E3232312E3134342E"
            "3232205030014C500360087C86027368960374656C0B0A160D34322E"
            "38312E3136392E313035205030014C500360087C8602746A96037465"
            "6C0BED000CF90F0CF9100CF9110CF01202F113FF38F6142832303230"
            "2D31322D32352032323A35383A32382064656C6976657279696E6720"
            "6120706F6C696379"
        )
        self.assertEqual(ServerListResponse.decode(encoded, extra="xxx"), raw)

    def test_sruct_list_decode(self):
        encoded = bytes.fromhex(
            "100129000B0A160E3139332E3131322E3233312E3630211F9030014C5C600870018602737A96066F74686572730B0A160D34322E38312E3137322E323135211F9030014C5C600870018602746A960374656C0B0A160B31342E32322E332E313134211F9030014C5C600870018602737A960374656C0B0A160E31342E3231352E3133382E3131302101BB30014C5C600870018602737A960374656C0B0A160D34322E38312E3136392E313030205030014C5C600870018602746A960374656C0B0A160E3131342E3232312E3134342E37362136B030014C5C6008700186027368960374656C0B0A160D3131332E39362E31322E3232342101BB30014C5C600870018602737A960374656C0B0A160D34322E38312E3137302E313232211F9030014C5C600870018602746A960374656C0B0A160E3131342E3232312E3134382E3637205030014C5C6008700186027368960374656C0B0A16116D7366776966692E33672E71712E636F6D211F9030014C5C60087C86066F746865727396066F74686572730B0A160C34322E38312E3137322E3633205030014C5C600870018602746A960374656C0B39000B0A160E3139332E3131322E3233312E3630211F9030014C5C600870018602737A96066F74686572730B0A160D34322E38312E3137322E323135211F9030014C5C600870018602746A960374656C0B0A160B31342E32322E332E313134211F9030014C5C600870018602737A960374656C0B0A160E31342E3231352E3133382E3131302101BB30014C5C600870018602737A960374656C0B0A160D34322E38312E3136392E313030205030014C5C600870018602746A960374656C0B0A160E3131342E3232312E3134342E37362136B030014C5C6008700186027368960374656C0B0A160D3131332E39362E31322E3232342101BB30014C5C600870018602737A960374656C0B0A160D34322E38312E3137302E313232211F9030014C5C600870018602746A960374656C0B0A160E3131342E3232312E3134382E3637205030014C5C6008700186027368960374656C0B0A16116D7366776966692E33672E71712E636F6D211F9030014C5C60087C86066F746865727396066F74686572730B0A160C34322E38312E3137322E3633205030014C5C600870018602746A960374656C0B425FE636545138406C7C80029005ACBCC900050A160E3130392E3234342E3132392E3135205030014C500360087C8602737A96066F74686572730B0A160D34322E38312E3136392E313035205030014C500360087C8602746A960374656C0B0A160C3131332E39362E31332E3434205030014C500360087C8602737A960374656C0B0A160E3131342E3232312E3134342E3232205030014C500360087C86027368960374656C0B0A160D34322E38312E3136392E313035205030014C500360087C8602746A960374656C0BD900050A160E3130392E3234342E3132392E3135205030014C500360087C8602737A96066F74686572730B0A160D34322E38312E3136392E313035205030014C500360087C8602746A960374656C0B0A160C3131332E39362E31332E3434205030014C500360087C8602737A960374656C0B0A160E3131342E3232312E3134342E3232205030014C500360087C86027368960374656C0B0A160D34322E38312E3136392E313035205030014C500360087C8602746A960374656C0BED000CF90F0CF9100CF9110CF01202F113FF38F61428323032302D31322D32352032323A35383A32382064656C6976657279696E67206120706F6C696379"
        )
        self.assertEqual(
            len(SsoServerInfo.decode_list(encoded, 2, extra="xxx")), 11
        )


if __name__ == "__main__":
    unittest.main()
